/*
 * xscanner.h
 *
 *  Created on: 2009-8-25
 *      Author: fanliangliang
 */

#ifndef XSCANNER_H_
#define XSCANNER_H_

#include <cstring>
#include <string>
#include <vector>
#include "toxic.h"

BEGIN_NAMESPACE_TOXIC

using std::string;
using std::vector;

enum CharClass {
	CHAR_WHITESPACE,
	CHAR_SYMBOLS,
	CHAR_DIGIT,
	CHAR_DOT,
	CHAR_OTHER,
	CHAR_CLASS_COUNT
};


enum StateType {
	STATE_START,
	STARE_IN_WHITESPACE,
	STATE_IN_INTEGRAL,
	STATE_ENTERING_FRACTIONAL,
	STATE_IN_FRACTIONAL,
	STATE_ACCEPT_SYMBOLS,
	STATE_ACCEPT_WHITESPACE,
	STATE_ACCEPT_INTEGER_NUMBER,
	STATE_ACCEPT_DECIMAL_NUMBER,
	STATE_TYPE_COUNT
};


enum TokenType {
	TOKEN_SYMBOLS,
	TOKEN_WHITESPACE,
	TOKEN_INTEGER_NUMBER,
	TOKEN_DECIMAL_NUMBER,
	TOKEN_ERROR
};


struct CharSequence {
	bool match(char ch) const { return sequence == 0 || std::strchr(sequence, ch) != 0; }

	CharClass type;
	const char* sequence;
};


struct ScanState {
	StateType state() const { return StateType(_data & 0x3F); }
	bool accept() const { return _data & 0x40; }
	bool advance() const { return _data & 0x80; }
	bool error() const { return _data == 0xFF; }

	unsigned char _data;
};


struct Token {
	Token(TokenType t, const string& s)
	:type(t), value(s) {}

	TokenType type;
	string value;
};


class Scanner {
public:
	Scanner(const string& str);
	bool hasNext() const;
	Token next();

private:
	char currentChar();
	char nextChar();

private:
	enum { MAX_TOKEN_LENGTH = 64 };

	string _str;
	string::size_type _pos;
	bool _eof;
	char _token[MAX_TOKEN_LENGTH + 1];
};


bool exprInfixToPostfix(string& postfix, const string& infix);

END_NAMESPACE_TOXIC

#endif /* XSCANNER_H_ */
